package com.lkd.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.lkd.common.VMSystem;
import com.lkd.config.TopicConfig;
import com.lkd.contract.SupplyChannel;
import com.lkd.contract.SupplyContract;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.ChannelEntity;
import com.lkd.entity.VendingMachineEntity;
import com.lkd.service.ChannelService;
import com.lkd.service.VendingMachineService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.util.ShardingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class VMSJob {

    @Autowired
    private VendingMachineService vendingMachineService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private MqttProducer mqttProducer;

    /**
     * 售货机服务定时补货扫描
     * @param param
     * @return
     * @throws Exception
     */
    @XxlJob("vmsSupplyScanJobHandler")
    public ReturnT<String> vmsSupplyScanJobHandler(String param) throws Exception{
        try {
            XxlJobLogger.log("售货机服务定时补货扫描");
            //获取 分片总数和当前分片索引
            ShardingUtil.ShardingVO shardingVo = ShardingUtil.getShardingVo();
            int numbers = shardingVo.getTotal();  //分片总数
            int index = shardingVo.getIndex(); //当前分片索引
            log.info("分片总数:{},当前分片索引:{}",numbers,index);
            //查询所有运营状态的售货机
            QueryWrapper<VendingMachineEntity> qw=new QueryWrapper<>();
            qw.lambda()
                    .eq(VendingMachineEntity::getVmStatus, VMSystem.VM_STATUS_RUNNING)
                    .apply("mod(id,"+numbers+" ) = "+index);
            List<VendingMachineEntity> vendingMachineEntityList = vendingMachineService.list(qw);
            //获取所有运营状态的售货机编码
            List<String> innerCodeList = vendingMachineEntityList.stream().map(vendingMachineEntity -> vendingMachineEntity.getInnerCode()).collect(Collectors.toList());
            for (String innerCode : innerCodeList) {
                //根据设备编号获取货道
                LambdaQueryWrapper<ChannelEntity> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ChannelEntity::getInnerCode,innerCode)
                        .ne(ChannelEntity::getSkuId,0L);
                List<ChannelEntity> channeles = channelService.list(queryWrapper);
                //获取每个货道的缺货数据
                List<SupplyChannel> supplyChannelList = channeles.stream().filter(channelEntity -> channelEntity.getMaxCapacity() - channelEntity.getCurrentCapacity() > 0).map(channel -> {
                    SupplyChannel supplyChannel = new SupplyChannel();
                    supplyChannel.setChannelId(channel.getChannelCode());
                    supplyChannel.setCapacity(channel.getMaxCapacity() - channel.getCurrentCapacity());
                    supplyChannel.setSkuId(channel.getSkuId());
                    supplyChannel.setSkuName(channel.getSku().getSkuName());
                    supplyChannel.setSkuImage(channel.getSku().getSkuImage());
                    return supplyChannel;
                }).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(supplyChannelList)){
                    continue;
                }
                //封装补货协议类
                SupplyContract supplyContract = new SupplyContract();
                supplyContract.setInnerCode(innerCode);
                supplyContract.setSupplyData(supplyChannelList);
                //发送到EMQ
                mqttProducer.send(TopicConfig.TASK_SUPPLY_TOPIC,2,supplyContract);
            }
            return ReturnT.SUCCESS;
        } catch (JsonProcessingException e) {
            XxlJobLogger.log("售货机服务定时补货扫描失败");
            return ReturnT.FAIL;
        }
    }
}
